﻿using Sasa.QualityTools.CodeAnalysis.Core.Models;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Properties;
using System;
using System.Collections.Generic;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels
{
    public class CodeInspectorViewModel : CodeAnalyzerViewModelBase<CodeInspector>
    {
        private FxCopErrorCodes errorCode;


        public ICollection<IFxCopReportValueCoordinator> Coordinators
        {
            get
            {
                return Model.Report.Coordinators;
            }
        }

        public ICodeAnalysisResultValueFilter Filter
        {
            get
            {
                return Model.Report.Filter;
            }
            set
            {
                Model.Report.Filter = value;
            }
        }

        public ICollection<ProblemViewModel> Problems { get; private set; }

        public ICollection<RuleViewModel> Rules { get; private set; }


        public CodeInspectorViewModel()
        {
            Problems = new List<ProblemViewModel>();
            Rules = new List<RuleViewModel>();
        }


        protected override void PerformCodeAnalysisCore()
        {
            errorCode = Model.PerformCodeAnalysis();

            foreach (var problem in Model.Report.Problems)
            {
                Problems.Add(new ProblemViewModel(problem));
            }
            foreach (var rule in Model.Report.Rules)
            {
                Rules.Add(new RuleViewModel(rule));
            }
        }

        protected override void LoadCodeAnalysisReportCore()
        {
            Model.LoadCodeAnalysisReport();

            foreach (var problem in Model.Report.Problems)
            {
                Problems.Add(new ProblemViewModel(problem));
            }
            foreach (var rule in Model.Report.Rules)
            {
                Rules.Add(new RuleViewModel(rule));
            }
        }

        protected override void NotifyCodeAnalysisPerformed()
        {
            Message = "Analyzing...";
            Status = CodeAnalysisStatus.Analyzing;
        }

        protected override void NotifyCodeAnalysisCompleted()
        {
            var messages = new List<string>();
            messages.Add((Problems.Count > 0) ? Problems.Count + " problems found." : "No problems found.");

            if (errorCode == FxCopErrorCodes.None)
            {
                Status = CodeAnalysisStatus.Completed;
            }
            else
            {
                Status = CodeAnalysisStatus.Warning;
                messages.Add("");
                messages.Add("Warning :");
                messages.AddRange(GetFxCopCmdErrorMessages(errorCode));
            }

            Message = String.Join(Environment.NewLine, messages);
        }

        protected override void NotifyCodeAnalysisFailed(Exception ex)
        {
            Message = ex.Message;
            Status = CodeAnalysisStatus.Failed;
        }

        private static IEnumerable<string> GetFxCopCmdErrorMessages(FxCopErrorCodes errorCode)
        {
            var messages = new List<string>();

            if (errorCode.HasFlag(FxCopErrorCodes.AnalysisError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfAnalysisError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.RuleExceptions))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseRuleThrowsException);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.ProjectLoadError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfProjectLoadError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.AssemblyLoadError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfAssemblyLoadError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.RuleLibraryLoadError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfRuleLibraryLoadError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.ImportReportLoadError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfReportLoadError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.OutputError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfOutputError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.CommandLineSwitchError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfSwitchError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.InitializationError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfInitializationError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.AssemblyReferencesError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfAssemblyReferencesError);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.BuildBreakingMessage))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseOfBuildBreaking);
            }
            if (errorCode.HasFlag(FxCopErrorCodes.UnknownError))
            {
                messages.Add(Resources.FxCopCmdFailedBecauseUnknownError);
            }

            return messages;
        }
    }
}
